package com.googlecode.archimedes.filegen.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.lang.builder.HashCodeBuilder;

import com.googlecode.archimedes.filegen.model.validator.Validator;

/**
 * A Member represents attributes of Entities
 * 
 * @author John Lema
 * @version $Id: Member.java 1830 2005-12-05 22:14:04 +0000 (Mon, 05 Dec 2005) erik $ Created on Sep 18, 2003
 */
public abstract class Member extends AbstractAsset implements Inheritable, Comparable<Member> {

	private String			memberName	= "UNDEFINED";
	private String			returnType	= "UNDEFINED";
	private String			visibility	= "UNDEFINED";
	private String			displayName	= "UNDEFINED";
	private String			description	= "No Description.";
	private String			columnName	= null;
	private boolean			required	= false;
	private boolean			readOnly	= false;
	private boolean			hidden		= false;
	private boolean			detailOnly	= false;
	private boolean			summaryOnly	= false;
	private Integer			order		= 0;

	public List<Validator>	validators	= new ArrayList<Validator>();

	/**
	 * The members Java name
	 * 
	 * @return MemberName a String of the memberName
	 */
	public String getMemberName() {
		return memberName;
	}

	/**
	 * Returns the Display Name
	 * 
	 * @return a String of the Display Name
	 */
	public String getDisplayName() {
		return displayName;
	}

	/**
	 * The members Display Name
	 * 
	 * @param displayName
	 *            like "First Name"
	 */
	public void setDisplayName(String displayName) {
		this.displayName = displayName;
	}

	/**
	 * Can only be "public", "private" or "protected" if anything else is entered, it defaults to "public"
	 * 
	 * @return the String visibility of this member
	 */
	public String getVisibility() {
		return visibility;
	}

	/**
	 * Can only be "public", "private" or "protected" if anything else is entered, it defaults to "public"
	 * 
	 * @param visibility
	 */
	public void setVisibility(String visibility) {
		if (visibility.equalsIgnoreCase("public") || visibility.equalsIgnoreCase("private") || visibility.equalsIgnoreCase("protected")) {
			this.visibility = visibility;
		} else {
			this.visibility = "public";
		}
	}

	/**
	 * like "firstname"
	 * 
	 * @param memberName
	 */
	public void setMemberName(String memberName) {
		this.memberName = memberName;
	}

	/**
	 * to be used IFF using FreeMarker tempaltes and Bean notation
	 * 
	 * @param Required
	 *            - Boolean
	 */
	public boolean isRequired() {
		return required;
	}

	/**
	 * Set if the member is required for complete
	 * 
	 * @param isRequired
	 *            - Boolean
	 */
	public void setRequired(boolean isRequired) {
		this.required = isRequired;
	}

	/**
	 * Gets the return type of the member
	 * 
	 * @return a String representing the return type
	 */
	public String getReturnType() {
		return returnType;
	}

	/**
	 * Sets the Return type of the member
	 * 
	 * @param returnType
	 *            like String, or Collection
	 */
	public void setReturnType(String returnType) {
		this.returnType = returnType;
	}

	/**
	 * Returns the readOnly.
	 * 
	 * @return boolean value of readOnly
	 */
	public boolean getReadOnly() {
		return readOnly;
	}

	/**
	 * Sets the readOnly
	 * 
	 * @param readOnly
	 *            The readOnly to set.
	 */
	public void setReadOnly(boolean readOnly) {
		this.readOnly = readOnly;
	}

	/**
	 * Returns an empty list as Members do not have any subordinate assets.
	 * 
	 * @see com.tps.filegen.model.Asset#getSubordinateAssets()
	 */
	public Collection<? extends Asset> getSubordinateAssets() {
		return new ArrayList<Asset>();
	}

	/**
	 * Returns if this member should be "hidden"
	 * 
	 * @return boolean value of hidden
	 */
	public boolean getHidden() {
		return hidden;
	}

	/**
	 * Sets if this member is hidden on not
	 * 
	 * @param hidden
	 *            The boolean to set.
	 */
	public void setHidden(boolean hidden) {
		this.hidden = hidden;
	}

	/**
	 * @return
	 */
	public List<Validator> getValidators() {
		if (this.validators == null) {
			return new ArrayList<Validator>();
		}
		return validators;
	}

	/**
	 * @param members
	 */
	public void setValidators(List<Validator> validators) {
		this.validators = validators;
	}

	public void addValidator(Validator validator) {
		validators.add(validator);
	}

	/**
	 * Returns the detailOnly.
	 * 
	 * @return boolean value of detailOnly
	 */
	public boolean getDetailOnly() {
		return detailOnly;
	}

	/**
	 * Sets the detailOnly
	 * 
	 * @param detailOnly
	 *            The detailOnly to set.
	 */
	public void setDetailOnly(boolean detailOnly) {
		this.detailOnly = detailOnly;
	}

	/**
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return new HashCodeBuilder(13, 29).append(memberName).toHashCode();
	}

	/**
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {

		if (obj != null && obj instanceof Member) {
			Member other = (Member) obj;
			return this.memberName.equals(other.memberName);
		}

		return false;
	}

	/**
	 * Returns the description.
	 * 
	 * @return String value of description
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * Sets the description
	 * 
	 * @param description
	 *            The description to set.
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * Returns the order.
	 * 
	 * @return Integer value of order
	 */
	public Integer getOrder() {
		return order;
	}

	/**
	 * Sets the order
	 * 
	 * @param order
	 *            The order to set.
	 */
	public void setOrder(Integer order) {
		this.order = order;
	}

	/**
	 * @see java.lang.Comparable#compareTo(T)
	 */
	public int compareTo(Member obj) {
		Member lhs = this;
		Member rhs = obj;
		return lhs.getOrder().compareTo(rhs.getOrder());
	}

	/**
	 * Returns the summaryOnly.
	 * 
	 * @return boolean value of summaryOnly
	 */
	public boolean getSummaryOnly() {
		return summaryOnly;
	}

	/**
	 * Sets the summaryOnly
	 * 
	 * @param summaryOnly
	 *            The summaryOnly to set.
	 */
	public void setSummaryOnly(boolean summaryOnly) {
		this.summaryOnly = summaryOnly;
	}

	/**
	 * @param columnName
	 *            the columnName to set
	 */
	public void setColumnName(String columnName) {
		this.columnName = columnName;
	}

	/**
	 * @return the columnName
	 */
	public String getColumnName() {
		if (columnName == null) {
			return convertCamelToUpper(getMemberName());
		}

		return columnName;
	}
}
